package org.zoomdev.zoom.dao.meta;

import com.alibaba.fastjson2.JSONWriter;
import org.zoomdev.zoom.common.json.JSON;
import org.zoomdev.zoom.dao.DaoException;
import org.zoomdev.zoom.dao.ddl.utils.MetaUtils;
import org.zoomdev.zoom.dao.ddl.utils.MysqlMetaUtils;

import javax.sql.DataSource;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public final class DatabaseMeta {

    private final String name;

    private final List<TableMeta> tables;

    public DatabaseMeta(String name, List<TableMeta> tables) {
        this.name = name;
        this.tables = tables;
    }

    public static DatabaseMeta fromFile(File file) throws IOException {
        try (InputStream is = Files.newInputStream(file.toPath())) {
            return JSON.parse(is, DatabaseMeta.class);
        }
    }

    public static DatabaseMeta fromDatabase(DataSource ds) {
        try {
            return fromDatabase(ds.getConnection());
        } catch (SQLException e) {
            throw new DaoException(e);
        }
    }

    public static DatabaseMeta fromDatabase(Connection conn) throws SQLException {

        List<TableMeta> list = new ArrayList<>();
        List<String> names = MetaUtils.getAllTableNames(conn);
        for (String name : names) {
            list.add(MysqlMetaUtils.getTableMeta(conn, name));
        }
        return new DatabaseMeta(conn.getCatalog(), list);
    }

    public static DatabaseMeta fromDatabase(String jdbcUrl,
                                            String username,
                                            String password) throws SQLException {

        // 建立数据库连接
        try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password)) {
            return fromDatabase(conn);
        }
    }

    @Override
    public boolean equals(Object o) {
        if (!(o instanceof DatabaseMeta)) return false;
        DatabaseMeta that = (DatabaseMeta) o;
        return Objects.equals(name, that.name)
                && Objects.equals(tables, that.tables);
    }

    public void toFile(File out) throws IOException {
        try (OutputStream os = Files.newOutputStream(out.toPath())) {
            com.alibaba.fastjson2.JSON.writeTo(os, this, JSONWriter.Feature.PrettyFormat);
        }
    }

    public String getName() {
        return name;
    }

    public List<TableMeta> getTables() {
        return tables;
    }


    public void diff(DatabaseMeta newMeta) {
        for (int i = 0, c = tables.size(); i < c; ++i) {

        }
    }
}
